{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ungraded Lab - Regularized Cost"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Goals\n",
    "In this lab you will:\n",
    "- extend the previous cost function with a regularization term.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from lab_utils import sigmoid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cost function for regularized logistic regression\n",
    "\n",
    "Below, you will implement the cost function for regularized logistic regression.\n",
    "\n",
    "Recall that for regularized logistic regression, the cost function is of the form\n",
    "$$J(\\mathbf{w},b) = \\frac{1}{m}  \\sum_{i=0}^{m-1} \\left[ -y^{(i)} \\log\\left(f_{\\mathbf{w},b}\\left( \\mathbf{x}^{(i)} \\right) \\right) - \\left( 1 - y^{(i)}\\right) \\log \\left( 1 - f_{\\mathbf{w},b}\\left( \\mathbf{x}^{(i)} \\right) \\right) \\right] + \\frac{\\lambda}{2}  \\sum_{j=0}^{n-1} w_j^2$$\n",
    "\n",
    "Compare this to the cost function without regularization (which you implemented in  a previous lab), which is of the form \n",
    "\n",
    "$$ J(\\mathbf{w},b) = \\frac{1}{m}\\sum_{i=0}^{m-1} \\left[ (-y^{(i)} \\log\\left(f_{\\mathbf{w},b}\\left( \\mathbf{x}^{(i)} \\right) \\right) - \\left( 1 - y^{(i)}\\right) \\log \\left( 1 - f_{\\mathbf{w},b}\\left( \\mathbf{x}^{(i)} \\right) \\right)\\right]$$\n",
    "\n",
    "The difference is the regularization term, which is $$\\frac{\\lambda}{2}  \\sum_{j=0}^{n-1} w_j^2$$\n",
    "\n",
    "Note, we do not regularize the parameter $b$. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Please complete the `compute_cost_reg` function to:\n",
    "- Calculate the cost over all examples in the training set exactly as you did in the `compute_cost` previously\n",
    "    - Create a variable outside the loop to store the costs\n",
    "    - Loop over all examples in the training set.\n",
    "        - calculate the cost for each training example \n",
    "            - Calculate `z`\n",
    "            - $ z =  w_0x_0^{(i)} + w_1x_1^{(i)} + b = \\mathbf{x}^{(i)T}\\mathbf{w} +b $\n",
    "            - Predict `f` where `g` is the sigmoid function\n",
    "                - $ f =  g(z) $\n",
    "            - Calculate the cost for each example  \n",
    "                $cost =  (-y^{(i)} * \\log f) - ((1 - y^{(i)})\\log( 1 - f))$\n",
    "         - Add this cost to the total cost variable created outside the loop   \n",
    "    - Get the sum of cost from all iterations and divide the total by the number of examples.\n",
    "\n",
    "        \n",
    "- Calculate the regularization term:        \n",
    "- Create a regularization cost variable outside the loop to accumulate the regularization cost\n",
    "- looping over `n` (number of features)\n",
    "    - calculate `w_j**2`\n",
    "    - Add this to the regularization cost variable\n",
    "    \n",
    "    \n",
    "- Get the total sum as the sum of the outputs from the two loops, that is add \n",
    "    - sum of cost from all the training examples divided by the number of examples\n",
    "    - sum of regularization cost from iterating over $w$ multiplied by $\\frac{\\lambda}{2}$\n",
    "\n",
    "As you are doing this, remember that the variables X and y are not scalar values but matrices of shape ($m, n$) and ($𝑚$, 1) respectively, where  $𝑛$ is the number of features and $𝑚$ is the number of training examples.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<details>\n",
    "  <summary><font size=\"2\" color=\"darkgreen\"><b>Hints</b></font></summary>\n",
    "       \n",
    " ```python  \n",
    "def compute_cost_reg(X, y, w, b, lambda_ = 1):\n",
    "    \"\"\"\n",
    "    Computes the cost over all examples\n",
    "    Args:\n",
    "      X : (array_like Shape (m,n)) data, m examples by n features\n",
    "      y : (array_like Shape (m,1)) target value \n",
    "      w : (array_like Shape (n,1)) Values of parameters of the model      \n",
    "      b : (array_like Shape (n,1)) Values of bias parameter of the model\n",
    "      lambda_ : (scalar, float)    Controls amount of regularization\n",
    "    Returns:\n",
    "      total_cost: (scalar)         cost \n",
    "    \"\"\"\n",
    "\n",
    "    m, n = X.shape\n",
    "    cost = 0.\n",
    "    for i in range(m):\n",
    "    ### START CODE HERE ### \n",
    "    ### BEGIN SOLUTION ###  \n",
    "        z = X[i] @  w + b\n",
    "        f = sigmoid(z)     \n",
    "        cost +=  -y[i]*np.log(f) - (1-y[i])*np.log(1-f)\n",
    "             \n",
    "    total_cost = (1/m) * cost\n",
    "    reg_cost = 0\n",
    "    for j in range(n):\n",
    "        reg_cost += (w[j]**2)\n",
    "    \n",
    "    total_cost = total_cost + (lambda_/2)*reg_cost\n",
    "    ### END SOLUTION ###  \n",
    "    ### END CODE HERE ### \n",
    "\n",
    "    return total_cost[0]\n",
    "   ```    \n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_cost_reg(X, y, w, b, lambda_ = 1):\n",
    "    \"\"\"\n",
    "    Computes the cost over all examples\n",
    "    Args:\n",
    "      X : (array_like Shape (m,n)) data, m examples by n features\n",
    "      y : (array_like Shape (m,1)) target value \n",
    "      w : (array_like Shape (n,1)) Values of parameters of the model      \n",
    "      b : (array_like Shape (n,1)) Values of bias parameter of the model\n",
    "      lambda_ : (scalar, float)    Controls amount of regularization\n",
    "    Returns:\n",
    "      total_cost: (scalar)         cost \n",
    "    \"\"\"\n",
    "\n",
    "    m, n = X.shape\n",
    "    cost = 0.\n",
    "    for i in range(m):\n",
    "    ### START CODE HERE ### \n",
    "\n",
    "    ### END CODE HERE ### \n",
    "\n",
    "    return total_cost[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run the cell below to check your implementation of the `compute_cost_reg` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(1)\n",
    "X_tmp = np.random.rand(5,6)\n",
    "y_tmp = np.array([0,1,0,1,0])\n",
    "initial_w = np.random.rand(X_tmp.shape[1]).reshape(-1,1)-0.5\n",
    "initial_b = 0.5\n",
    "lambda_ = 1\n",
    "cost = compute_cost_reg(X_tmp, y_tmp, initial_w, initial_b, lambda_)\n",
    "\n",
    "print(\"Regularized cost at initial w, b:\", cost)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Expected Output**:\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <b>Regularized cost at initial w,b: </b> 0.8782251500458396 </td>\n",
    "  </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
